package org.activequant.core.domainmodel.marketscanner;

import static org.activequant.util.tools.IdentityUtils.equalsTo;
import static org.activequant.util.tools.IdentityUtils.safeCompare;
import static org.activequant.util.tools.IdentityUtils.safeHashCode;

import java.io.Serializable;

import org.activequant.core.types.Expiry;
/**
 * ScanCriteria implements Comparable&lt;ScanCriteria&gt;, Serializable<br/>
 * Holds the following associated variables:
 * <ul>
 * <li>id(Long)</li>
 * <li>vendor(String)</li>
 * <li>numberOfRows(int)</li>
 * <li>instrument(String)</li>
 * <li>locationCode(String)</li>
 * <li>scanCode(String)</li>
 * <li>abovePrice(double)</li>
 * <li>belowPrice(double)</li>
 * <li>aboveVolume(int)</li>
 * <li>averageOptionVolumeAbove(int)</li>
 * <li>marketCapAbove(double)</li>
 * <li>marketCapBelow(double)</li>
 * <li>moodyRatingAbove(String)</li>
 * <li>moodyRatingBelow(String)</li>
 * <li>spRatingAbove(String)</li>
 * <li>spRatingBelow(String)</li>
 * <li>maturityDateAbove(Expiry)</li>
 * <li>maturityDateBelow(Expiry)</li>
 * <li>couponRateAbove(double)</li>
 * <li>couponRateBelow(double)</li>
 * <li>excludeConvertible(String)</li>
 * <li>scannerSettingPairs(String)</li>
 * <li>stockTypeFilter(String)</li>
 * </ul>
 * @author Dimitar
 *
 */
public class ScanCriteria implements Comparable<ScanCriteria>, Serializable{
	private static final long serialVersionUID = -3373322976345588675L;

	public static final int NOT_SET = -1;

	private Long id = null;
	private String vendor;
    private int numberOfRows = NOT_SET;
    private String instrument;
    private String locationCode;
    private String scanCode;
    private double abovePrice = NOT_SET;
    private double belowPrice = NOT_SET;
    private int aboveVolume = NOT_SET;
    private int averageOptionVolumeAbove = NOT_SET;
    private double marketCapAbove = NOT_SET;
    private double marketCapBelow = NOT_SET;
    private String moodyRatingAbove;
    private String moodyRatingBelow;
    private String spRatingAbove;
    private String spRatingBelow;
    private Expiry maturityDateAbove;
    private Expiry maturityDateBelow;
    private double couponRateAbove = NOT_SET;
    private double couponRateBelow = NOT_SET;
    private String excludeConvertible;
    private String scannerSettingPairs;
    private String stockTypeFilter;
    
    
    
	public ScanCriteria(int numberOfRows, String vendor, String instrument, String locationCode, String scanCode, double abovePrice, double belowPrice, int aboveVolume, int averageOptionVolumeAbove, double marketCapAbove, double marketCapBelow, String moodyRatingAbove, String moodyRatingBelow,
			String spRatingAbove, String spRatingBelow, Expiry maturityDateAbove, Expiry maturityDateBelow, double couponRateAbove, double couponRateBelow, String excludeConvertible, String scannerSettingPairs, String stockTypeFilter) {
		this.numberOfRows = numberOfRows;
		this.vendor=vendor;
		this.instrument = instrument;
		this.locationCode = locationCode;
		this.scanCode = scanCode;
		this.abovePrice = abovePrice;
		this.belowPrice = belowPrice;
		this.aboveVolume = aboveVolume;
		this.averageOptionVolumeAbove = averageOptionVolumeAbove;
		this.marketCapAbove = marketCapAbove;
		this.marketCapBelow = marketCapBelow;
		this.moodyRatingAbove = moodyRatingAbove;
		this.moodyRatingBelow = moodyRatingBelow;
		this.spRatingAbove = spRatingAbove;
		this.spRatingBelow = spRatingBelow;
		this.maturityDateAbove = maturityDateAbove;
		this.maturityDateBelow = maturityDateBelow;
		this.couponRateAbove = couponRateAbove;
		this.couponRateBelow = couponRateBelow;
		this.excludeConvertible = excludeConvertible;
		this.scannerSettingPairs = scannerSettingPairs;
		this.stockTypeFilter = stockTypeFilter;
	}
	
	public ScanCriteria(ScanCriteria scanCriteria) {
		this.id = scanCriteria.getId();
		this.numberOfRows = scanCriteria.getNumberOfRows();
		this.vendor = scanCriteria.getVendor();
		this.instrument = scanCriteria.getInstrument();
		this.locationCode = scanCriteria.getLocationCode();
		this.scanCode = scanCriteria.getScanCode();
		this.abovePrice = scanCriteria.getAbovePrice();
		this.belowPrice = scanCriteria.getBelowPrice();
		this.aboveVolume = scanCriteria.getAboveVolume();
		this.averageOptionVolumeAbove = scanCriteria.getAverageOptionVolumeAbove();
		this.marketCapAbove = scanCriteria.getMarketCapAbove();
		this.marketCapBelow = scanCriteria.getMarketCapBelow();
		this.moodyRatingAbove = scanCriteria.getMoodyRatingAbove();
		this.moodyRatingBelow = scanCriteria.getMoodyRatingBelow();
		this.spRatingAbove = scanCriteria.getSpRatingAbove();
		this.spRatingBelow = scanCriteria.getSpRatingBelow();
		this.maturityDateAbove = scanCriteria.getMaturityDateAbove();
		this.maturityDateBelow = scanCriteria.getMaturityDateBelow();
		this.couponRateAbove = scanCriteria.getCouponRateAbove();
		this.couponRateBelow = scanCriteria.getCouponRateBelow();
		this.excludeConvertible = scanCriteria.getExcludeConvertible();
		this.scannerSettingPairs = scanCriteria.getScannerSettingPairs();
		this.stockTypeFilter = scanCriteria.getStockTypeFilter();
	}

	public ScanCriteria(){
		
	}
	 @Override
	 public ScanCriteria clone(){
		 return new ScanCriteria(numberOfRows, vendor, instrument, locationCode, scanCode, abovePrice, belowPrice, aboveVolume, averageOptionVolumeAbove, marketCapAbove, marketCapBelow, moodyRatingAbove, moodyRatingBelow, 
				 spRatingAbove, spRatingBelow, maturityDateAbove, maturityDateBelow,couponRateAbove,couponRateBelow,excludeConvertible, scannerSettingPairs, stockTypeFilter);
	 }
	
	 /**
		 * {@inheritDoc}
		 */
	public int hashCode() {
		// ATTENTION: keep in sync with compareTo()
		return 
		  safeHashCode(this.scanCode)
	    + safeHashCode(this.instrument)
		+ safeHashCode(this.locationCode)
		+ safeHashCode(this.numberOfRows) 
		+ safeHashCode(this.vendor)
		+ safeHashCode(this.abovePrice)
		+ safeHashCode(this.belowPrice)
		+ safeHashCode(this.aboveVolume)
		+ safeHashCode(this.averageOptionVolumeAbove)
		+ safeHashCode(this.marketCapAbove)
		+ safeHashCode(this.marketCapBelow)
		+ safeHashCode(this.moodyRatingAbove)
		+ safeHashCode(this.moodyRatingBelow)
		+ safeHashCode(this.spRatingAbove)
		+ safeHashCode(this.spRatingBelow)
		+ safeHashCode(this.maturityDateAbove)
		+ safeHashCode(this.maturityDateBelow)
		+ safeHashCode(this.couponRateAbove)
		+ safeHashCode(this.couponRateBelow)
		+ safeHashCode(this.excludeConvertible)
		+ safeHashCode(this.scannerSettingPairs)
		+ safeHashCode(this.stockTypeFilter);
	}		
	
	/**
	 * {@inheritDoc}
	 */
	public int compareTo(ScanCriteria other) {
		// ATTENTION: keep in sync with hashCode();
		int rc;
		rc = safeCompare(this.scanCode, other.scanCode);
		if(rc != 0) return rc;
		rc = safeCompare(this.instrument, other.instrument);
		if(rc != 0) return rc;
		rc = safeCompare(this.locationCode, other.locationCode);
		if(rc != 0) return rc;
		rc = safeCompare(this.numberOfRows, other.numberOfRows);
		if(rc != 0) return rc;
		rc = safeCompare(this.vendor, other.vendor);
		if(rc != 0) return rc;		
		rc = safeCompare(this.abovePrice, other.abovePrice);
		if(rc != 0) return rc;
		rc = safeCompare(this.belowPrice, other.belowPrice);
		if(rc != 0) return rc;
		rc = safeCompare(this.aboveVolume, other.aboveVolume);
		if(rc != 0) return rc;
		rc = safeCompare(this.averageOptionVolumeAbove, other.averageOptionVolumeAbove);
		if(rc != 0) return rc;
		rc = safeCompare(this.marketCapAbove, other.marketCapAbove);
		if(rc != 0) return rc;
		rc = safeCompare(this.marketCapBelow, other.marketCapBelow);
		if(rc != 0) return rc;
		rc = safeCompare(this.moodyRatingAbove, other.moodyRatingAbove);
		if(rc != 0) return rc;
		rc = safeCompare(this.moodyRatingBelow, other.moodyRatingBelow);
		if(rc != 0) return rc;
		rc = safeCompare(this.spRatingAbove, other.spRatingAbove);
		if(rc != 0) return rc;
		rc = safeCompare(this.spRatingBelow, other.spRatingBelow);
		if(rc != 0) return rc;
		rc = safeCompare(this.maturityDateAbove, other.maturityDateAbove);
		if(rc != 0) return rc;
		rc = safeCompare(this.maturityDateBelow, other.maturityDateBelow);
		if(rc != 0) return rc;
		rc = safeCompare(this.couponRateAbove, other.couponRateAbove);
		if(rc != 0) return rc;
		rc = safeCompare(this.couponRateBelow, other.couponRateBelow);
		if(rc != 0) return rc;
		rc = safeCompare(this.excludeConvertible, other.excludeConvertible);
		if(rc != 0) return rc;
		rc = safeCompare(this.scannerSettingPairs, other.scannerSettingPairs);
		if(rc != 0) return rc;
		rc = safeCompare(this.stockTypeFilter, other.stockTypeFilter);
		if(rc != 0) return rc;
		
		return rc;
	}
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean equals(Object other) {
		// NOTE: delegates to compareTo()
		return equalsTo(this, other);
	}
	
	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public boolean hasId() {
		return id != null;
	}
	
	public int getNumberOfRows() {
		return numberOfRows;
	}

	public void setNumberOfRows(int numberOfRows) {
		this.numberOfRows = numberOfRows;
	}

	public String getInstrument() {
		return instrument;
	}

	public void setInstrument(String instrument) {
		this.instrument = instrument;
	}

	public String getLocationCode() {
		return locationCode;
	}

	public void setLocationCode(String locationCode) {
		this.locationCode = locationCode;
	}

	public String getScanCode() {
		return scanCode;
	}

	public void setScanCode(String scanCode) {
		this.scanCode = scanCode;
	}

	public double getAbovePrice() {
		return abovePrice;
	}

	public void setAbovePrice(double abovePrice) {
		this.abovePrice = abovePrice;
	}

	public double getBelowPrice() {
		return belowPrice;
	}

	public void setBelowPrice(double belowPrice) {
		this.belowPrice = belowPrice;
	}

	public int getAboveVolume() {
		return aboveVolume;
	}

	public void setAboveVolume(int aboveVolume) {
		this.aboveVolume = aboveVolume;
	}

	public int getAverageOptionVolumeAbove() {
		return averageOptionVolumeAbove;
	}

	public void setAverageOptionVolumeAbove(int averageOptionVolumeAbove) {
		this.averageOptionVolumeAbove = averageOptionVolumeAbove;
	}

	public double getMarketCapAbove() {
		return marketCapAbove;
	}

	public void setMarketCapAbove(double marketCapAbove) {
		this.marketCapAbove = marketCapAbove;
	}

	public double getMarketCapBelow() {
		return marketCapBelow;
	}

	public void setMarketCapBelow(double marketCapBelow) {
		this.marketCapBelow = marketCapBelow;
	}

	public String getMoodyRatingAbove() {
		return moodyRatingAbove;
	}

	public void setMoodyRatingAbove(String moodyRatingAbove) {
		this.moodyRatingAbove = moodyRatingAbove;
	}

	public String getMoodyRatingBelow() {
		return moodyRatingBelow;
	}

	public void setMoodyRatingBelow(String moodyRatingBelow) {
		this.moodyRatingBelow = moodyRatingBelow;
	}

	public String getSpRatingAbove() {
		return spRatingAbove;
	}

	public void setSpRatingAbove(String spRatingAbove) {
		this.spRatingAbove = spRatingAbove;
	}

	public String getSpRatingBelow() {
		return spRatingBelow;
	}

	public void setSpRatingBelow(String spRatingBelow) {
		this.spRatingBelow = spRatingBelow;
	}

	public Expiry getMaturityDateAbove() {
		return maturityDateAbove;
	}

	public void setMaturityDateAbove(Expiry maturityDateAbove) {
		this.maturityDateAbove = maturityDateAbove;
	}

	public Expiry getMaturityDateBelow() {
		return maturityDateBelow;
	}

	public void setMaturityDateBelow(Expiry maturityDateBelow) {
		this.maturityDateBelow = maturityDateBelow;
	}

	public double getCouponRateAbove() {
		return couponRateAbove;
	}

	public void setCouponRateAbove(double couponRateAbove) {
		this.couponRateAbove = couponRateAbove;
	}

	public double getCouponRateBelow() {
		return couponRateBelow;
	}

	public void setCouponRateBelow(double couponRateBelow) {
		this.couponRateBelow = couponRateBelow;
	}

	public String getExcludeConvertible() {
		return excludeConvertible;
	}

	public void setExcludeConvertible(String excludeConvertible) {
		this.excludeConvertible = excludeConvertible;
	}

	public String getScannerSettingPairs() {
		return scannerSettingPairs;
	}

	public void setScannerSettingPairs(String scannerSettingPairs) {
		this.scannerSettingPairs = scannerSettingPairs;
	}

	public String getStockTypeFilter() {
		return stockTypeFilter;
	}

	public void setStockTypeFilter(String stockTypeFilter) {
		this.stockTypeFilter = stockTypeFilter;
	}

	 public String getVendor() {
		return vendor;
	}

	public void setVendor(String vendor) {
		this.vendor = vendor;
	}

	@Override
	    public String toString() {
			String ret= id==null?"":(id+"\t");
			ret += numberOfRows==NOT_SET?"":(numberOfRows+"\t");
			ret += instrument==null?"":(instrument+ "\t"); 
			ret += vendor==null?"":(vendor+ "\t");
			ret += locationCode==null?"":(locationCode+ "\t");
			ret +=  scanCode==null?"":(scanCode + "\t");
			ret +=  abovePrice==NOT_SET?"":(abovePrice+ "\t");
			ret +=  belowPrice==NOT_SET?"":(belowPrice+ "\t");
			ret +=  aboveVolume==NOT_SET?"":(aboveVolume+ "\t");
			ret +=  averageOptionVolumeAbove==NOT_SET?"":(averageOptionVolumeAbove+ "\t");
			ret +=  marketCapAbove==NOT_SET?"":(marketCapAbove+ "\t");
			ret +=  marketCapBelow==NOT_SET?"":(marketCapBelow+ "\t");
			ret +=  moodyRatingAbove==null?"":(moodyRatingAbove+ "\t");
			ret +=  moodyRatingBelow==null?"":(moodyRatingBelow+ "\t");
			ret +=  spRatingAbove==null?"":(spRatingAbove+ "\t");
			ret +=  spRatingBelow==null?"":(spRatingBelow+ "\t");
			ret +=  maturityDateAbove==null?"":(maturityDateAbove+ "\t");
			ret +=  maturityDateBelow==null?"":(maturityDateBelow+ "\t");
			ret +=  couponRateAbove==NOT_SET?"":(couponRateAbove+ "\t");
			ret +=  couponRateBelow==NOT_SET?"":(couponRateBelow+ "\t");
			ret +=  excludeConvertible==null?"":(excludeConvertible+ "\t");
			ret +=  scannerSettingPairs==null?"":(scannerSettingPairs+ "\t");
			ret +=  stockTypeFilter==null?"":(stockTypeFilter);
			return ret;
	 }
	 
}
